﻿using System;
using SharpSvn;
using SharpSvn.Security;
using System.Windows.Forms;

namespace svnbox {
    public class SvnCommand {

        SvnClient cl;

        public string RootPath;
        public string User;
        public string Pass;
        public string Host;

        public bool NetworkAvailable = false;

        private static void debug(string s) { System.Diagnostics.Debug.WriteLine("{SvnCommand} " + s); }
        private static void debug(string source, Exception s) {
            System.Diagnostics.Debug.WriteLine("{SvnCommand} " + source + " " + s.Message);
            if (s.InnerException != null) {
                System.Diagnostics.Debug.WriteLine("{SvnCommand} " + source + " InnerEx : " + s.InnerException.Message);
            }
        }

        public SvnClient Client() {
            if (!NetworkAvailable)
                return null;

            cl = new SvnClient();

            cl.Authentication.SslServerTrustHandlers += new EventHandler<SharpSvn.Security.SvnSslServerTrustEventArgs>(delegate(object sender, SvnSslServerTrustEventArgs e) {
                e.AcceptedFailures = e.Failures;
                e.Save = true;
            });
            cl.Authentication.Clear();
            cl.Authentication.UserNamePasswordHandlers += delegate(object sender, SvnUserNamePasswordEventArgs e) {
                e.UserName = User;
                e.Password = Pass;
                e.Save = true;
            };

            return cl;
        }

        #region Svn Methods
        // Ive used diffrents methods for each action 
        // to handle diffrents inputs parametres and diffrents output types

        public SvnInfoEventArgs Info(string sPath) {
            using (SvnClient cl = Client()) {
                if (cl == null) return null;
                SvnInfoEventArgs inf;
                cl.GetInfo(SvnTarget.FromString(sPath), out inf);
                return inf;
            }
        }

        public SvnInfoEventArgs Info(Uri uri) {
            using (SvnClient cl = Client()) {
                if (cl == null) return null;
                SvnInfoEventArgs inf;
                cl.GetInfo(SvnTarget.FromUri(uri), out inf);
                return inf;
            }
        }


        public bool Commit(string commitLog = "AnonymeCommit") {
            using (SvnClient cl = Client()) {
                if (cl == null) { return false;   }
                SvnCommitResult res;            
                try {
                    if (cl.Commit(RootPath, new SvnCommitArgs { LogMessage = commitLog, Depth = SvnDepth.Infinity, ThrowOnError = true }, out res)) {
                        if (res != null)
                            debug("PostCommitRevision: " + res.Revision.ToString());
                        return true;
                    } else {
                        debug("Commit failed !");
                    }
                } catch (SvnException se) {
                    debug("SvnCommit Error : ", se);
                } catch (Exception se) { debug("SvnCommit Error1 :", se); }
            }
            return false;
        }


        public bool Update(string sPath) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    if (cl.Update(sPath, new SvnUpdateArgs())) {
                        if (sPath == RootPath)
                            debug("Update success - now your ROOT WC is HEAD versioned....");
                        else {
                            debug("Update object success " + sPath);
                        }
                        return true;
                    }
                } catch (SvnException se) {
                    debug("SvnUpdate Error :", se);
                } catch (Exception se) { debug("SvnUpdate Error1 :", se); }
                return false;
            }
        }


        public bool CleanUp() {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    if (cl.CleanUp(RootPath, new SvnCleanUpArgs())) {
                        return true;
                    }
                } catch (SvnException se) {
                    debug("SvnCleanUp Error :" + se.Message);
                } catch (Exception se) { debug("SvnCleanUp Error1 :", se); }
                return false;
            }
        }

        public bool CheckOut() {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    cl.CheckOut(new SvnUriTarget(new Uri(Host)), RootPath);
                    debug("Checkout success has applied ......");
                    return true;
                } catch (SvnException se) {
                    debug("SvnCheckout Error :", se);
                } catch (Exception se) { debug("SvnCheckout Error1 :", se); }
                return false;
            }
        }

        public bool Rename(string sPath, string sOldPath) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    cl.Delete(sOldPath);
                    cl.Add(sPath);
                    debug("Rename " + sPath);
                    return true;
                } catch (Exception se) { debug("SvnMove Exception ", se); }
            }
            return false;
        }

        public bool Resolve(string sPath, SvnAccept acpt) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    if (cl.Resolve(sPath, acpt)) {
                        return true;
                    }
                } catch (SvnException se) {
                    debug("SvnResolve Error :" + se.Message);
                } catch (Exception se) { debug("SvnResolve Error1 :", se); }
            }
            return false;
        }

        public bool IsWorkingCopy(string path) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    Uri uri = cl.GetUriFromWorkingCopy(path);
                    return uri != null;
                } catch (SvnException se) {
                    debug("IsWorkingCopy Error :", se);
                } catch (Exception se) { debug("IsWorkingCopy Error1 :", se); }
                return false;
            }
        }

        public bool Add(string sPath) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    if (cl.Add(sPath, new SvnAddArgs())) {
                        debug("Added " + sPath);
                        return true;
                    }
                } catch (SvnException se) {
                    debug("SvnAdd Exception ", se);
                } catch (Exception se) { debug("SvnAdd Error1 :", se); }
            }

            return false;
        }

        public bool Delete(string sPath) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    if (cl.Delete(sPath, new SvnDeleteArgs())) {
                        debug("Deleted " + sPath);
                        return true;
                    }
                } catch (SvnException se) {
                    debug("SvnDelete Exception ", se);
                } catch (Exception se) { debug("SvnDelete Error1 :", se); }
            }
            return false;
        }

        public bool ForceDelete(string sPath) {
            using (SvnClient cl = Client()) {
                if (cl == null) return false;
                try {
                    if (cl.Delete(sPath, new SvnDeleteArgs() { Force = true })) {
                        debug("ForceDeleted " + sPath);
                        return true;
                    }
                } catch (SvnException se) {
                    debug("SvnForceDelete Exception ", se);
                } catch (Exception se) { debug("SvnForceDelete Error1 :", se); }
            }
            return false;
        }
        #endregion

    }
}
